package com.kcs.dc.service.logic;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.xml.transform.TransformerException;
import com.kcs.dc.service.bean.request.wsSettleReqBody;
import com.kcs.dc.service.bean.request.wsSettleReqCopyBody;
import com.kcs.dc.service.bean.request.wsSettleReqHeader;
import com.kcs.dc.service.bean.request.wsSettleRequest;
import com.kcs.dc.service.bean.response.wsSettleResBody;
import com.kcs.dc.service.bean.response.wsSettleResHeader;
import com.kcs.dc.service.bean.response.wsSettleResponseCPT;
import com.kcs.dc.service.dao.wsDealCenterDAO;
import com.kcs.dc.service.dao.wsSettleModel;
import com.kcs.dc.service.dao.wsRetAdModel;
import com.kcs.dc.service.utils.LogToDB;
import com.kcs.common.utils.ConnectionUtils;
import com.kcs.common.utils.Constant;
import com.kcs.common.utils.ConstantMessage;
import com.kcs.common.utils.LogWriter;
import com.kcs.common.utils.PropertySet;
import com.kcs.common.utils.PropsUtils;
import com.kcs.common.utils.XmlUtils;
import com.kcs.common.utils.commonUtils;

public class settleGenerateBL extends generateResponse{
	
	private final static String SYSTEM_PAST_SETTLE = "DCTP";
	private final static String SERVICE_ONLINE = "WS0002O";
	private final static String REC_BATCH = "BATCH";
	private final static String SERVICE_BATCH = "WS0002B";
	private final static int MAX_REC_ONLINE = 20;
	private final static int MAX_REC_BATCH = 50;
	private final static String[] SETTLEFLAG = {"S","R"};
	private final static String DEFALUT_STATUS = "U";
	private final static String ERROR_STATUS = "Y";
	private final static String NO_ERROR_STATUS = "N";
	private final static String DEFALUT_DESC = "";
	private int[] ser_req_id_arry = {};
	wsDealCenterDAO dao = null;
	
	
	
    
    public settleGenerateBL() {
		dao = new wsDealCenterDAO();
	}

	public wsSettleResponseCPT generateResponse(wsSettleRequest request) {
    	LogWriter.info("<=====================================================>", Constant.LOGGER_WEBSERVICE);
    	LogWriter.info("=====Start here : call wsSettle=====", Constant.LOGGER_WEBSERVICE);
    	
        wsSettleReqHeader reqHeader = request.getHeader();
        wsSettleReqBody[] reqBody = request.getBody();        
        String xmlrequest = "";
        wsSettleReqCopyBody[] copyBody = null;       

        Connection retConn = null;
        Connection dcConn = null;  
        
        try { 
        	// -- Get connection 2 system.
        	retConn = getConnectionRETAD();
        	dcConn = getConnectionDealCenter(); 
        	
        	// Copy reqVar[] to coypReqVar[] : default err_status and err_desc.
        	copyBody = copyRequestBody(reqBody);
        	
        	//--log request
        	xmlrequest = genRequestXML(reqHeader, reqBody);
        	LogWriter.info("=====XML Request : " + xmlrequest, Constant.LOGGER_WEBSERVICE);
        	
        	// Check Header.
        	wsSettleResponseCPT resChkHd = basicCheckHeader(dcConn, reqHeader, copyBody);
        	if(resChkHd == null){

        		// Check Body[]	        			        		
        		wsSettleResponseCPT resChkBd = basicCheckBody(dcConn, copyBody, reqHeader);    			
        			if (resChkBd == null){
        				
        				 if (retConn == null){
        					 LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_CONN_RETAD), Constant.LOGGER_WEBSERVICE);
        			            return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_CONN_RETAD, 
        			           		 	PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_CONN_RETAD), 0);
            			 }else{
            				 return prepareAndSettle(retConn, dcConn, reqHeader, copyBody);
            			 }
        				 
        			}else{
        				// have error body.
        				LogWriter.info("=====Finish process : call wsSettle=====", Constant.LOGGER_WEBSERVICE);
        				return resChkBd;
        			}                			
        	 }else{
        		 // have error header.
        		 LogWriter.info("=====Finish process : call wsSettle=====", Constant.LOGGER_WEBSERVICE);
        		 return resChkHd;
        	 }

        
        } catch (Exception ex) { 
        	 return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_EXCEPTION, 
               		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_EXCEPTION) + ex.getMessage(), 0);
        } finally{
    		ConnectionUtils.closeConnection(dcConn);
    		ConnectionUtils.closeConnection(retConn);
    	}
    }
    
    private wsSettleReqCopyBody[] copyRequestBody(wsSettleReqBody[] reqBody){
    	LogWriter.info("=====Copy RequestBody[] to temp=====", Constant.LOGGER_WEBSERVICE); 
    	
    	ArrayList<wsSettleReqCopyBody> array = new ArrayList<wsSettleReqCopyBody>();
    	wsSettleReqCopyBody[] modelsCopy = null;
    	wsSettleReqCopyBody model = null;
    	
    	for (int i = 0; i < reqBody.length; i++) {
    		model = new wsSettleReqCopyBody();
    		
    		LogWriter.debug("ReqBody[" + i + "] : " + reqBody[i].getDealId(), Constant.LOGGER_WEBSERVICE);
    		model.setDealId(reqBody[i].getDealId());
    		model.setCcyAmt(reqBody[i].getCcyAmt());
    		model.setSettleFlag(reqBody[i].getSettleFlag());
    		model.setSourceRef(reqBody[i].getSourceRef());
    		model.setErrStatus(DEFALUT_STATUS);
    		model.setErrDesc(DEFALUT_DESC);
    		
    		array.add(model);
		}
    	
    	modelsCopy = (wsSettleReqCopyBody[]) array.toArray(new wsSettleReqCopyBody[array.size()]);
    	
		return modelsCopy;
    	
    }
    
    private wsSettleResBody[] moveToResponseBody(wsSettleReqCopyBody[] copyBody){
    	
    	ArrayList<wsSettleResBody> array = new ArrayList<wsSettleResBody>();
    	wsSettleResBody[] modelsRes = null;
    	wsSettleResBody model = null;
    	            	
    	for (int i = 0; i < copyBody.length; i++) {
    		model = new wsSettleResBody();
    		
    		model.setDealId(copyBody[i].getDealId());
    		model.setSourceRef(copyBody[i].getSourceRef());
    		model.setErrStatus(copyBody[i].getErrStatus());
    		model.setErrDesc(copyBody[i].getErrDesc());
    		
    		array.add(model);
		}
    	
    	modelsRes = (wsSettleResBody[]) array.toArray(new wsSettleResBody[array.size()]);
    	
		return modelsRes;
    	
    }    
    
	private wsSettleResponseCPT basicCheckHeader(Connection dcConn, wsSettleReqHeader reqHeader,
			wsSettleReqCopyBody[] copyBody) throws Exception {
		
		
		try{   	
			// Check Authenticate RequestID. 
			boolean exitLogRequest = isAuthenRequest(dcConn, reqHeader.getRequestID(), reqHeader.getSystem(), reqHeader.getServiceID());
			
			//--log request
			LogWriter.debug("=====Insert Log Request into table.=====", Constant.LOGGER_WEBSERVICE);
			ser_req_id_arry = new int[copyBody.length];
			for (int i = 0; i < copyBody.length; i++) {
				ser_req_id_arry[i] = LogToDB.logRequest(dcConn, reqHeader.getSystem(), reqHeader.getServiceID(), reqHeader.getRequestID(), reqHeader.getNumOfReqRec(), 
		    			copyBody[i].getDealId(), "" , "", "", "", new BigDecimal(copyBody[i].getCcyAmt()), copyBody[i].getSettleFlag(), copyBody[i].getSourceRef());
				LogWriter.info("=====ser_req_log_id[" + i + "] : "+ ser_req_id_arry[i] + "Deal :" + copyBody[i].getDealId(), Constant.LOGGER_WEBSERVICE);
			}
	    	
			/*LogToDB.logRequest(dcConn,reqHeader.getSystem(), reqHeader.getServiceID(),reqHeader.getRequestID(), xmlrequest);*/
				    	    	
	    	LogWriter.info("=====Prepare basic check header.=====", Constant.LOGGER_WEBSERVICE);
		   	 if(!exitLogRequest) {
		   		LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AUTHEN_REQ), Constant.LOGGER_WEBSERVICE);
		            return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_AUTHEN_REQ, 
		           		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AUTHEN_REQ), 0);
		     }	
	    	 // Check Header input.
		   	 if(!isHeaderValid(reqHeader.getSystem(), reqHeader.getServiceID(), reqHeader.getRequestID())) {
		   		LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_REQH_BLANK), Constant.LOGGER_WEBSERVICE);
	            return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_REQH_BLANK, 
	           		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_REQH_BLANK), 0);
		      }
		   	 // Check Header (Number of Request Record.
		   	 if(isNullOrBlankString(String.valueOf(reqHeader.getNumOfReqRec()))){
		   		LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_BLANK), Constant.LOGGER_WEBSERVICE);
	            return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_NUM_BLANK, 
	           		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_BLANK), 0);
		   	 }
		   	 // Check isNumeric of NumOfReqRec.
		   	 if(!commonUtils.isNumeric(String.valueOf(reqHeader.getNumOfReqRec()))){
		   		LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_NUMERIC), Constant.LOGGER_WEBSERVICE);
	            return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_NUM_NUMERIC, 
	           		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_NUMERIC), 0);
		   	 }   	 
		   	 // Check Authenticate system. 
		   	 if(!isAuthenSystem(dcConn, reqHeader.getSystem(), reqHeader.getServiceID())) {
		   		 	LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AUTHEN_SYS), Constant.LOGGER_WEBSERVICE);
		            return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_AUTHEN_SYS, 
		           		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AUTHEN_SYS), 0);
		      }	   	
		   	 // Check NumOrReqRec each serviceID
		   	 if(reqHeader.getServiceID().equals(SERVICE_BATCH) && reqHeader.getNumOfReqRec() > MAX_REC_BATCH ){	
		   		 
	   			LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_MORE50), Constant.LOGGER_WEBSERVICE);
	            return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_NUM_MORE50, 
	           		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_MORE50), 0);	   		    	
		   		 
		   	 }else if(reqHeader.getServiceID().equals(SERVICE_ONLINE) && reqHeader.getNumOfReqRec() > MAX_REC_ONLINE){	
		   		 
		   		LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_MORE20), Constant.LOGGER_WEBSERVICE);
	            return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_NUM_MORE20, 
	           		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_MORE20), 0);  
		   		 
		   	 }
		   	 // Check NumOfReqRec = reqVar.length
		   	 if(reqHeader.getNumOfReqRec() != copyBody.length){
		   		LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_CONSISTENT), Constant.LOGGER_WEBSERVICE);
	            return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_NUM_CONSISTENT, 
	           		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_NUM_CONSISTENT), 0); 
		   	 }
		}catch(Exception e){
			throw new Exception();
		}
	   	 
	   	 return null;
    }
    
	private wsSettleResponseCPT basicCheckBody(Connection dcConn, wsSettleReqCopyBody[] copyBody,
			wsSettleReqHeader reqHeader) {
    	
    	boolean isError = false;
    	LogWriter.info("=====Prepare basic check body.=====", Constant.LOGGER_WEBSERVICE);
   	 	 // Check Body input.
    	for (int i = 0; i < copyBody.length; i++) {
    		   		
    		if(!isBodyValid(copyBody[i].getDealId(), String.valueOf(copyBody[i].getCcyAmt()), copyBody[i].getSettleFlag())){
    			copyBody[i].setErrStatus(ERROR_STATUS);
    			copyBody[i].setErrDesc(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_REQB_SET_BLANK));  
    			LogWriter.error("Row[" + (i+1) + "] " + PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_REQB_SET_BLANK), Constant.LOGGER_WEBSERVICE);
    	   		isError = true;

    		/*}else if(!commonUtils.isNumeric(String.valueOf(copyBody[i].getCcyAmt()))){
    	   		copyBody[i].setErrStatus(ERROR_STATUS);
    	   		copyBody[i].setErrDesc(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AMT_NUMERIC));    	   		 
    	   		LogWriter.error("Row[" + (i+1) + "] " + PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AMT_NUMERIC), Constant.LOGGER_WEBSERVICE);
    	   		isError = true;*/
    	   		
    	   	 }else if(copyBody[i].getCcyAmt() <= 0){
    	   		copyBody[i].setErrStatus(ERROR_STATUS);
    	   		copyBody[i].setErrDesc(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AMT_NUMERIC));  
    	   		LogWriter.error("Row[" + (i+1) + "] " + PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AMT_NUMERIC), Constant.LOGGER_WEBSERVICE);
    	   		isError = true;
    	   	 }else if(!copyBody[i].getSettleFlag().equals(SETTLEFLAG[0])
    	   			 && !copyBody[i].getSettleFlag().equals(SETTLEFLAG[1])){
    	   		copyBody[i].setErrStatus(ERROR_STATUS);
    	   		copyBody[i].setErrDesc(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_SETTLE_FLAG));  
    	   		LogWriter.error("Row[" + (i+1) + "] " + PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_SETTLE_FLAG), Constant.LOGGER_WEBSERVICE);
    	   		isError = true;
    	   	 }  		
		}
    	
    	if (isError && reqHeader.getServiceID().equals(SERVICE_ONLINE)){
    		return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_LOGIC, 
              		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_LOGIC), 0);
    	}
   	 
	   	 return null;
   }
    
   private boolean isBodyValid(String deal_id, String ccy_amt, String settle_flag) {
		
		boolean somethingNull = (isNullOrBlankString(deal_id) || 
								 isNullOrBlankString(ccy_amt) || 
								 isNullOrBlankString(settle_flag));

		if (somethingNull) return false;
							
		return true;
		
	}
   
   private String genRequestXML(wsSettleReqHeader header, wsSettleReqBody[] body){
   	
   	String xmlRequest = null;
   	
   	PropertySet reqH = new PropertySet();
   	reqH.setType("wsSettleReqHeader");
   	
   	PropertySet modelH = new PropertySet();
   	modelH.setProperty("system", header.getSystem());
   	modelH.setProperty("serviceID", header.getServiceID());
   	modelH.setProperty("requestID", header.getRequestID());
	modelH.setProperty("numberOfReqRec", String.valueOf(header.getNumOfReqRec()));   	
   	reqH.addChild(modelH);
   	
   	PropertySet reqB = new PropertySet();
   	reqB.setType("wsSettleReqBody");  	
   	for (int i = 0; i < body.length; i++) {
   		PropertySet modelB = new PropertySet();
   		modelB.setProperty("Row",  String.valueOf(i+1));
   	   	modelB.setProperty("dealID", body[i].getDealId());
   	   	modelB.setProperty("ccyAmt", String.valueOf(body[i].getCcyAmt()));
   	   	modelB.setProperty("settleFlag", body[i].getSettleFlag());
   	   	modelB.setProperty("sourceRef", body[i].getSourceRef());
   	   	reqB.addChild(modelB); 		
   	}
   	
   	
   	PropertySet req = new PropertySet();
   	req.addChild(reqH);
   	req.addChild(reqB);
   	
   	
		try {
			xmlRequest = XmlUtils.propertySetToXmlString(req);
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			xmlRequest = "";
			LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_EXCEPTION) + ": " + e.getMessage(), Constant.LOGGER_WEBSERVICE);
		}
   	
		return xmlRequest;
   }   
   
   private String genResponseXML(wsSettleResHeader header, wsSettleResBody[] body, int numOfSuccess){
   	
   	String xmlRequest = null;
   	
   	PropertySet reqH = new PropertySet();
   	reqH.setType("wsSettleResHeader");
	
   	PropertySet modelH = new PropertySet();
   	modelH.setProperty("system", header.getSystem());
   	modelH.setProperty("serviceID", header.getServiceID());
   	modelH.setProperty("requestID", header.getRequestID());
   	modelH.setProperty("respCode", header.getRespCode());
   	modelH.setProperty("respDesc", header.getRespDesc());
   	modelH.setProperty("respTime", header.getRespTime());
   	modelH.setProperty("numberOfSuccess", String.valueOf(numOfSuccess));
   	reqH.addChild(modelH);
   	   	
   	PropertySet reqB = new PropertySet();
   	reqB.setType("wsSettleResBody");   	
   	for (int i = 0; i < body.length; i++) {
   		PropertySet modelB = new PropertySet();
   		modelB.setProperty("Row",  String.valueOf(i+1));
   		modelB.setProperty("dealID", body[i].getDealId());
   		modelB.setProperty("srcRef", body[i].getSourceRef());
   		modelB.setProperty("errorStatus", body[i].getErrStatus());
   		modelB.setProperty("errorStatusDesc", body[i].getErrDesc());
       	reqB.addChild(modelB);
		}
   	 	
   	PropertySet req = new PropertySet();
   	req.addChild(reqH);
   	req.addChild(reqB);
   	
   	
		try {
			xmlRequest = XmlUtils.propertySetToXmlString(req);
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			xmlRequest = "";
			LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_EXCEPTION) + ": " + e.getMessage(), Constant.LOGGER_WEBSERVICE);
		}
   	
		return xmlRequest;
   }   
    
	private wsSettleResponseCPT prepareAndSettle(Connection retConn, Connection dcConn, 
			wsSettleReqHeader reqHeader, wsSettleReqCopyBody[] copyBody) throws Exception {
    		   	
    	ArrayList<String> dealList = new ArrayList<String>();
    	for (int i = 0; i < copyBody.length; i++) {
    		dealList.add(copyBody[i].getDealId());
		}
		
    	// Prepare query from RET-AD and Insert/Update tbl.Deals
    	if(!getRetAdAndPrepareDeals(retConn, dcConn, dao, dealList, reqHeader.getSystem())){
    		
    		return prepareSettleAndMovement(dcConn, copyBody, dao, reqHeader);
    		
    	}else{
    		// Can't insert/update Deals.
    		return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_LOGIC, 
             		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_LOGIC) + " : " + 
             		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_INS_DEALS) + " OR " +
             		 PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_UPD_DEALS), 0);
    	
    	}
	}
    	
	private boolean getRetAdAndPrepareDeals(Connection retConn, Connection dcConn, 
			wsDealCenterDAO dao, ArrayList<String> dealList, String mod_user) throws Exception {
    	
		boolean isError = false;
		
		try{
			// Prepare query from RET-AD   	
	    	LogWriter.debug("=====Select data from ret-ad=====", Constant.LOGGER_WEBSERVICE);
	    	wsRetAdModel[] RetadModel = dao.getDataRetAD("", "", "", "", dealList, retConn);   	
			
	    	if(RetadModel != null){
	     		
	    		for (int i = 0; i < RetadModel.length; i++) {
	    			
	    			/*Call Store all Insert And Update.*/
	    			LogWriter.debug("Prepare Insert/Update Deals.", Constant.LOGGER_WEBSERVICE);
	    			if(!dao.insertDealCenter(RetadModel[i], dcConn, mod_user ))
						LogWriter.error("DealId : " + RetadModel[i].getDealID() +  " ==> " + 
										PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_INS_DEALS), Constant.LOGGER_WEBSERVICE);
	    			
					if (!dao.updateDealsCenter(RetadModel[i].getDealID(),
							RetadModel[i].getOutstdAmt(), 
							RetadModel[i].getDocType().toUpperCase(), 
							dcConn, mod_user,
							RetadModel[i].getCifNumber(), RetadModel[i].getComments() ))
						LogWriter.error("DealId : " + RetadModel[i].getDealID() +  " ==> " + 
										PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_UPD_DEALS), Constant.LOGGER_WEBSERVICE);
			
	    		} // End loop.
			}
    	
		}catch(Exception e){
			throw new Exception();
		}

		return isError;
    	
    }	
	
	private wsSettleResponseCPT prepareSettleAndMovement(Connection dcConn,
			wsSettleReqCopyBody[] copyBody, wsDealCenterDAO dao,
			wsSettleReqHeader reqHeader) throws Exception {
		
   		wsSettleModel dcModel = null;
   		int num_rec_success_online = 0;
   		int num_rec_success_batch = 0;
   		int num_rec_error = 0;
   		
		String date_ymd = commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.yyyymmdd);
		
		try{
			LogWriter.info("=====Loop Settle/Rollover on Deals/Movement.=====", Constant.LOGGER_WEBSERVICE);
			for (int i = 0; i < copyBody.length; i++) {
				boolean isError = false;  
				
				/*Check error status = 'U' then do process */
				if(copyBody[i].getErrStatus().equals(DEFALUT_STATUS)){									
					// Get OutstdAmt & DealAmt (New & Past)
					if (reqHeader.getSystem().equals(SYSTEM_PAST_SETTLE) ||
							reqHeader.getSystem().equals(REC_BATCH)){
						//Past Settlement or Batch
						dcModel = dao.getDealsSettlePast(copyBody[i].getDealId(), date_ymd, dcConn);
				
					}else{
						//Today Settlement
						dcModel = dao.getDealsFromSettle(copyBody[i].getDealId(), date_ymd, dcConn); 
					}
					
					if (dcModel == null){  // Not found record				
							copyBody[i].setErrStatus(ERROR_STATUS);
							copyBody[i].setErrDesc(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_STATUS_DEALS));
							LogWriter.error("DealId : " + copyBody[i].getDealId() +  " ==> " + 
									PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_STATUS_DEALS), Constant.LOGGER_WEBSERVICE);
							
							isError = true;						
					}else{ 
						// Update OutstAmt on Log Table.
						// Create new Connection [seperate from transaction]
						Connection logConn = getConnectionDealCenter(); 
						LogToDB.updateCCY1OUT(logConn, new BigDecimal(dcModel.getOutsdAmt()), ser_req_id_arry[i]);
						ConnectionUtils.closeConnection(logConn);
						//========================================================================================
						
						// Have data on Deals (#Else 1)
						if (copyBody[i].getSettleFlag().equals(SETTLEFLAG[0])){  
							// Settle Flag = 'S'
							if (copyBody[i].getCcyAmt() > dcModel.getOutsdAmt()){  // CCY_AMT > OUTSTANDING					
									copyBody[i].setErrStatus(ERROR_STATUS);
									copyBody[i].setErrDesc(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_USEAMT_MORE_OUTSAMT));
									LogWriter.error("DealId : " + copyBody[i].getDealId() +  " ==> " + 
											PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_USEAMT_MORE_OUTSAMT), Constant.LOGGER_WEBSERVICE);	
									
									isError = true;
							}
	
						}else{  
							// Settle Flag = 'R'				
							double out_amt = dcModel.getOutsdAmt() + copyBody[i].getCcyAmt();
							out_amt = Math.round( out_amt * 100.00 ) / 100.00;
							if (out_amt > dcModel.getDealAmt()){  // OUT_AMT > DEAL_AMT1						
									copyBody[i].setErrStatus(ERROR_STATUS);
									copyBody[i].setErrDesc(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_REVERSE_AMT));
									LogWriter.error("DealId : " + copyBody[i].getDealId() +  " ==> " + 
											PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_REVERSE_AMT), Constant.LOGGER_WEBSERVICE);	
									
									isError = true;
							}
							
						}
					
						// If not have error then insert deals_movement.
						if(!isError){
							LogWriter.debug( (i+1) + "=====Insert DealMovement ["+ copyBody[i].getDealId() + "]", Constant.LOGGER_WEBSERVICE);
							if(dao.insertDealMovement(dcConn, copyBody[i].getDealId(), date_ymd, 
									(copyBody[i].getSettleFlag().equals(SETTLEFLAG[0])) ? copyBody[i].getCcyAmt()*-1 : copyBody[i].getCcyAmt(), 
									reqHeader.getSystem(), reqHeader.getRequestID(), copyBody[i].getSourceRef(), reqHeader.getServiceID())){
								copyBody[i].setErrStatus(NO_ERROR_STATUS);
								copyBody[i].setErrDesc(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.INF_SUCCESS));
								LogWriter.info("DealId : " + copyBody[i].getDealId() +  " ==> " + 
										PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.INF_SUCCESS), Constant.LOGGER_WEBSERVICE);	
							}else{
								copyBody[i].setErrStatus(ERROR_STATUS);
								copyBody[i].setErrDesc(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_INS_DEALS_MOVE));
								LogWriter.error("DealId : " + copyBody[i].getDealId() +  " ==> " + 
										PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_INS_DEALS_MOVE), Constant.LOGGER_WEBSERVICE);
	
								isError = true;
							}
						}
						
					} // End (#Else 1)				
				}
			
				if(reqHeader.getServiceID().equals(SERVICE_BATCH)){
					dcConn.commit();  // commit per transaction.
					
					if(copyBody[i].getErrStatus().equals(NO_ERROR_STATUS))
						num_rec_success_batch++;	
					
					if(copyBody[i].getErrStatus().equals(ERROR_STATUS))
						num_rec_error++;
					
				}else{
					if(copyBody[i].getErrStatus().equals(ERROR_STATUS)){
						num_rec_error++;
						dcConn.rollback();
						break;
					}else{
						num_rec_success_online++;
					}
				}	
			} // End For loop.
			
			// Case: Online (Success all then commit transaction.
			if (num_rec_success_online == copyBody.length)
				dcConn.commit();  // commit all deals per 1 call ws.
			
			// Case: Batch (success >= 1 then show header success too).
			if (num_rec_success_batch >= 1)
				num_rec_error = 0;
			
			
			LogWriter.info("=====Finish process : call wsSettle=====", Constant.LOGGER_WEBSERVICE);
			
			if (num_rec_error > 0){
				return genereateErrorResponse(dcConn, reqHeader, moveToResponseBody(copyBody), ConstantMessage.ERR_LOGIC,  
						PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_LOGIC), 
								reqHeader.getServiceID().equals(SERVICE_BATCH)? num_rec_success_batch : 0);				
			}else{
				return generateSuccessResponse(dcConn, reqHeader, moveToResponseBody(copyBody), 
						reqHeader.getServiceID().equals(SERVICE_BATCH)? num_rec_success_batch : num_rec_success_online);
			}
		
	
		}catch (Exception e) {
			// TODO: handle exception
			try {
				dcConn.rollback();
			} catch (SQLException ex) {
				// TODO Auto-generated catch block
				LogWriter.error("Rollback error : " + ex.getMessage(), Constant.LOGGER_WEBSERVICE);
			}
			throw new Exception();
		}	
	}
	
	private wsSettleResponseCPT genereateErrorResponse(Connection dcConn,
			wsSettleReqHeader reqHeader, wsSettleResBody[] respBody,
			String returnCode, String errorDesc, int numOfSuccess) {
    	    
    	wsSettleResponseCPT returnedResponse = null;
    	
    	String res_time = commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.ddmmyyyyhhmmsswithslash);
    	String xmlResponse = "";
    	 
    	try{
	    	    	
    		// Case : Settlement
    		wsSettleResHeader respHeaderSet = new wsSettleResHeader(reqHeader.getServiceID(), reqHeader.getRequestID(),
    				reqHeader.getSystem(), returnCode, errorDesc, res_time, numOfSuccess);
	        
	      
	        returnedResponse = new wsSettleResponseCPT(respHeaderSet,respBody);
	        
	        //--log response	  
	        xmlResponse = genResponseXML(respHeaderSet, respBody, numOfSuccess);
	        LogWriter.info("=====XML Response : " + xmlResponse, Constant.LOGGER_WEBSERVICE);
	        LogWriter.info("=====Insert Log Response into table.=====", Constant.LOGGER_WEBSERVICE);
	        for (int i = 0; i < respBody.length; i++) {
	        	LogToDB.logResponse(dcConn, returnCode, errorDesc, respBody.length, respBody[i].getErrStatus(), respBody[i].getErrDesc(), ser_req_id_arry[i]);
			}
			
			/*LogToDB.logResponse(dcConn, ser_req_id,
			respHeaderSet.getSystem(), respHeaderSet.getServiceID(),
			respHeaderSet.getRequestID(), returnCode, errorDesc, xmlResponse);*/	           				
			
    	}catch(Exception ex){
    		LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_EXCEPTION), Constant.LOGGER_WEBSERVICE);
    	}
		        
        return returnedResponse;
    }
    
    private wsSettleResponseCPT generateSuccessResponse(Connection dcConn, 
    		wsSettleReqHeader reqHeader, wsSettleResBody[] respBody, int numOfSuccess) {
    	
		wsSettleResponseCPT returnedResponse = null;
		
        String respCode = ConstantMessage.INF_SUCCESS;
        String respDesc = PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.INF_SUCCESS);
        String res_time = commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.ddmmyyyyhhmmsswithslash);
        String xmlResponse = "";
       
        try{      		
    		// Case : Settle
    		wsSettleResHeader respHeader = new wsSettleResHeader(reqHeader.getServiceID(), reqHeader.getRequestID(),
    				reqHeader.getSystem(), respCode, respDesc, res_time, numOfSuccess);
	        
	      
	        returnedResponse = new wsSettleResponseCPT(respHeader,respBody);
	        
	        //--log response	 
	        xmlResponse = genResponseXML(respHeader, respBody, numOfSuccess);
	        LogWriter.info("=====XML Response : " + xmlResponse, Constant.LOGGER_WEBSERVICE);
	        LogWriter.info("=====Insert Log Response into table.=====", Constant.LOGGER_WEBSERVICE);
	        
	        for (int i = 0; i < respBody.length; i++) {
	        	LogToDB.logResponse(dcConn, respCode, respDesc, respBody.length, respBody[i].getErrStatus(), respBody[i].getErrDesc(), ser_req_id_arry[i]);
			}
	        
			/*LogToDB.logResponse(dcConn, ser_req_id,
					respHeader.getSystem(), respHeader.getServiceID(),
					respHeader.getRequestID(), respCode, respDesc, xmlResponse);*/
      
        }catch(Exception e){
        	LogWriter.error(PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_EXCEPTION), Constant.LOGGER_WEBSERVICE);
        }
        
        return returnedResponse;
    }
  
}
